// Decompiled on 周六 2月 22 19:31:49 CST 2025 with Zomboid Decompiler v0.1.3 using Vineflower.
package zombie.fileSystem;

import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;

public final class MemoryFileDevice implements IFileDevice {
    @Override
    public IFile createFile(IFile child) {
        return new MemoryFileDevice.MemoryFile(child, this);
    }

    @Override
    public void destroyFile(IFile file) {
    }

    @Override
    public InputStream createStream(String path, InputStream child) throws IOException {
        return null;
    }

    @Override
    public void destroyStream(InputStream stream) {
    }

    @Override
    public String name() {
        return "memory";
    }

    private static class MemoryFile implements IFile {
        final MemoryFileDevice m_device;
        byte[] m_buffer;
        long m_size;
        long m_pos;
        IFile m_file;
        boolean m_write;

        MemoryFile(IFile iFile, MemoryFileDevice memoryFileDevice) {
            this.m_device = memoryFileDevice;
            this.m_buffer = null;
            this.m_size = 0L;
            this.m_pos = 0L;
            this.m_file = iFile;
            this.m_write = false;
        }

        @Override
        public boolean open(String string, int _int) {
            assert this.m_buffer == null;

            this.m_write = (_int & 2) != 0;
            if (this.m_file != null) {
                if (this.m_file.open(string, _int)) {
                    if ((_int & 1) != 0) {
                        this.m_size = this.m_file.size();
                        this.m_buffer = new byte[(int)this.m_size];
                        this.m_file.read(this.m_buffer, this.m_size);
                        this.m_pos = 0L;
                    }

                    return true;
                }
            } else if ((_int & 2) != 0) {
                return true;
            }

            return false;
        }

        @Override
        public void close() {
            if (this.m_file != null) {
                if (this.m_write) {
                    this.m_file.seek(FileSeekMode.BEGIN, 0L);
                    this.m_file.write(this.m_buffer, this.m_size);
                }

                this.m_file.close();
            }

            this.m_buffer = null;
        }

        @Override
        public boolean read(byte[] _byte, long long1) {
            long long0 = this.m_pos + long1 < this.m_size ? long1 : this.m_size - this.m_pos;
            System.arraycopy(this.m_buffer, (int)this.m_pos, _byte, 0, (int)long0);
            this.m_pos += long0;
            return false;
        }

        @Override
        public boolean write(byte[] _byte, long long3) {
            long long0 = this.m_pos;
            long long1 = (long)this.m_buffer.length;
            long long2 = this.m_size;
            if (long0 + long3 > long1) {
                long long4 = Math.max(long1 * 2L, long0 + long3);
                this.m_buffer = Arrays.copyOf(this.m_buffer, (int)long4);
            }

            System.arraycopy(_byte, 0, this.m_buffer, (int)long0, (int)long3);
            this.m_pos += long3;
            this.m_size = long0 + long3 > long2 ? long0 + long3 : long2;
            return true;
        }

        @Override
        public byte[] getBuffer() {
            return this.m_buffer;
        }

        @Override
        public long size() {
            return this.m_size;
        }

        @Override
        public boolean seek(FileSeekMode fileSeekMode, long _long) {
            switch (fileSeekMode) {
                case BEGIN:
                    assert _long <= this.m_size;

                    this.m_pos = _long;
                    break;
                case CURRENT:
                    assert 0L <= this.m_pos + _long && this.m_pos + _long <= this.m_size;

                    this.m_pos += _long;
                    break;
                case END:
                    assert _long <= this.m_size;

                    this.m_pos = this.m_size - _long;
            }

            boolean _boolean = this.m_pos <= this.m_size;
            this.m_pos = Math.min(this.m_pos, this.m_size);
            return _boolean;
        }

        @Override
        public long pos() {
            return this.m_pos;
        }

        @Override
        public InputStream getInputStream() {
            return this.m_file != null ? this.m_file.getInputStream() : null;
        }

        @Override
        public IFileDevice getDevice() {
            return this.m_device;
        }

        @Override
        public void release() {
            this.m_buffer = null;
        }
    }
}
